        var watchers = [];
        //编译函数
        function compile(node, vm) {
            var reg = /\{\{(.*)\}\}/; // 来匹配{{xxx}}中的xxx
            var reg_data = /:data-(.*)/;
            //如果是元素节点
            if (node.nodeType === 1) {
                var attr = node.attributes;
                //解析元素节点的所有属性
                for (let i = 0; i < attr.length; i++) {
                    if(reg_data.test(attr[i].nodeName)){
                        var key = reg_data.exec(attr[i].nodeName)[1];
                        node.dataset[key] = get_field(vm.data, attr[i].nodeValue);
                        // node.removeAttribute(':data-' + key);
                    }


                    if(attr[i].nodeName == ':click'){
                        var func_name = attr[i].nodeValue;
                        var func = get_field(vm.methods, func_name);
                        node.addEventListener('click', function(arg){
                            func.call(vm, arg);
                        });
                    }


                    if (attr[i].nodeName == 'v-model') {
                        var name = attr[i].nodeValue //看看是与哪一个数据相关
                        node.addEventListener('input', function(e) { //将与其相关的数据改为最新值
                            set_field(vm.data, name, e.target.value);
                        });
                        watchers.push(new Watcher(vm, node, name, function(){
                            node.value = get_field(vm.data, name);
                        }));
                        node.value = get_field(vm.data, name); //将data中的值赋予给该node
                        // node.removeAttribute('v-model');
                    }
                }
                for (var i = 0; i < node.childNodes.length; i++) {
                    compile(node.childNodes[i], vm);
                }
            }

            //如果是文本节点
            if (node.nodeType === 3) {
                if (reg.test(node.nodeValue)) {
                    var name = reg.exec(node.nodeValue)[1]; //获取到匹配的字符串
                    name = name.trim();
                    //node.nodeValue = vm[name]; //将data中的值赋予给该node
                    watchers.push(new Watcher(vm, node, name)) //绑定一个订阅者
                }
            }
        }

        //在向碎片化文档中添加节点时，每个节点都处理一下

        function nodeToFragment(node, vm) {
            var fragment = document.createDocumentFragment();
            var child;
            while (child = node.firstChild) {
                compile(child, vm);
                fragment.appendChild(child);
            }
            return fragment
        }

        //实现一个响应式监听属性的函数。一旦有赋新值就发生变化 
        function defineReactive(obj, key, val) {
            var dep = new Dep();
            var func_update_dep = function(){
                if (Dep.target) {
                    dep.addSub(Dep.target)
                } else {
                    if(watchers.length > 0){
                        for (var i = watchers.length - 1; i >= 0; i--) {
                            var n = watchers[i].name.split('.');
                            if(n.length > 0){
                                if(n[n.length - 1] === key && !dep.subs.includes(watchers[i])){
                                    dep.addSub(watchers[i]);
                                }
                            }
                        }
                    }
                }
            }
            Object.defineProperty(obj, key, {
                enumerable: true,
                configurable: true,
                get: function() {
                    func_update_dep();
                    return val
                },
                set: function(newVal) {
                    if (newVal === val) {
                        return
                    }

                    if (newVal instanceof Object && !(newVal instanceof Array)){ //重新给新设置的对象设置监听
                        observe(newVal);
                    }

                    val = newVal;

                    func_update_dep();

                    //一旦更新立马通知
                    dep.notify();
                }
            })
        }

        //实现一个观察者，对于一个实例 每一个属性值都进行观察。
        function observe(obj) {
            for (let key of Object.keys(obj)) {
                defineReactive(obj, key, obj[key]);
                if (obj[key] instanceof Object && !(obj[key] instanceof Array)) {
                    observe(obj[key]);
                }
            }
        }

        //这里是实现方法，采用递归读取对象的属性值
        function get_field(data, fields, pattern) {
            var arr = fields.split('.');
            var key = arr.shift();
            var value = data[key];

            if (value == null) {
                return value;
            } else if (arr.length == 0) {
                if (!pattern) return value;
                var type = Object.prototype.toString.call(value).replace('[object ', '').replace(']', '');
                if (pattern === true) {
                    return type;
                } else if (!pattern) {
                    return value;
                } else {
                    return type == pattern;
                }
            }

            var result = get_field(value, arr.join('.'), pattern);
            return result;
        }

        function set_field(data, fields, val, pattern) {
            var arr = fields.split('.');
            var key = arr.shift();
            var value = data[key];
            if (value == null && arr.length != 0) { //不存在这个属性
                return;
            } else if (arr.length == 0) {
                data[key] = val;
                return;
            }
            set_field(data[key], arr.join('.'), val, pattern);
        }

        //通过字符串给obj生成字段
        function gen_field(obj, fields_str){
            debugger
            var n = fields_str.split('.');
            var idx = 0;
            while(idx < n.length){
                var path = "";
                for (var i = 0; i <= idx; i++) {
                    path += n[i] + ".";
                }
                path = path.substring(0, path.lastIndexOf('.'));
                var parent = path.substring(0, path.lastIndexOf('.'));
                var item = get_field(obj, path);
                if(item === undefined || item === null){
                    if(parent === ""){
                        defineReactive(obj, n[idx], {});
                    } else {
                        defineReactive(get_field(obj, parent), n[idx], {});
                    }
                    
                }
                idx++;
            }
        }

        //Watcher监听者
        function Watcher(vm, node, name, callback) {
            Dep.target = this;
            this.vm = vm;
            this.node = node;
            this.name = name;
            this.callback = callback;
            this.update();
            Dep.target = null;
        }

        Watcher.prototype = {
            update() {
                this.get();
                this.node.nodeValue = this.value //更改节点内容的关键
                if(this.callback){
                    this.callback();
                }
            },
            get() {
                this.value = get_field(this.vm.data, this.name) //触发相应的get
                if(this.value === null || this.value === undefined){
                    this.value = undefined;
                    console.warn(this.name + " is " + this.value);
                    gen_field(this.vm.data, this.name);
                }
            }
        }

        //dep构造函数
        function Dep() {
            this.subs = []
        }
        Dep.prototype = {
            addSub(sub) {
                this.subs.push(sub)
            },
            notify() {
                this.subs.forEach(function(sub) {
                    sub.update();
                })
            }
        }

        //拷贝resource对象的所有方法到target对象中
        function proxy_methods(target, resource){
            for (var key of Object.keys(resource)) {
                target[key] = function(arg){
                    resource[key].call(target, arg);
                }
            }
        }


        //Aut构造函数     
        //观察data中的所有属性值，注意增添了observe

        function Aut(options) {
            this.data = options.data;
            this.methods = options.methods;
            proxy_methods(this, this.methods);
            observe(this.data)
            var id = options.el;
            var dom = nodeToFragment(document.getElementById(id), this)
            //处理完所有节点后，重新把内容添加回去
            document.getElementById(id).appendChild(dom)
        }